#include "command.h"

#define BUFFER_SIZE 1024

void generate_hash_with_salt(const char *password, char **hashed_password,
                             unsigned char **salt, char *salt_hex) {
  // 生成随机盐值
  *salt = malloc(16);  // 分配足够的空间存储盐值
  if (!*salt) {
    fprintf(stderr, "Memory allocation failed for salt.\n");
    return;
  }
  // 使用 /dev/urandom 来生成随机盐值
  FILE *urandom = fopen("/dev/urandom", "rb");
  if (urandom == NULL) {
    fprintf(stderr, "Failed to open /dev/urandom.\n");
    free(*salt);
    return;
  }
  fread(*salt, 1, 16, urandom);  // 读取16字节作为盐值
  fclose(urandom);

  // 将盐值转换为十六进制字符串
  //   char salt_hex[33];  // 16字节 * 2 + 1（null terminator）
  for (int i = 0; i < 16; i++) {
    sprintf(&salt_hex[i * 2], "%02x", (*salt)[i]);
  }

  // 为格式字符串分配足够的空间
  char format[65];  // "$2a$08$" + 22 个字符的盐值 + 31 个字符的哈希值 + null
                    // terminator
  snprintf(format, sizeof(format), "$2a$08$%s", salt_hex);

  // 生成哈希值
  *hashed_password = crypt(password, format);  // 使用 crypt 生成哈希值
  if (*hashed_password == NULL) {
    fprintf(stderr, "crypt() function failed.\n");
    free(*salt);
    return;
  }
}

// 打印sql语句到日志中
void print_sql_to_log(const char *level, const char *user_name,
                      const char *sql) {
  // 存日志信息
  char buf_log[2048] = {0};
  sprintf(buf_log, "(%s)sql %s", user_name, sql);
  log_log(level, "SERVER", buf_log);
}

int get_parameter(char *key, char *value) {
  FILE *file = fopen("config.ini", "r");
  while (1) {
    char line[100];
    bzero(line, sizeof(line));
    // 读一行数据
    char *res = fgets(line, sizeof(line), file);
    if (res == NULL) {
      log_log("ERROR", "SERVER", "没有要找的内容");
      char buf[] = "没有要找的内容 \n";
      memcpy(value, buf, strlen(buf));
      return -1;
    }
    // 处理数据
    char *line_key = strtok(line, "=");
    if (strcmp(key, line_key) == 0) {
      // 要找的内容
      char *line_value = strtok(NULL, "=");
      memcpy(value, line_value, strlen(line_value));
      return 0;
    }
  }
}

void compute_sha256_hash(const char *filename, char **hash_out) {
  FILE *file = fopen(filename, "rb");
  if (!file) {
    log_log("ERROR", "SERVER", "文件打开失败！");
    perror("Error opening file");
    return;
  }

  EVP_MD_CTX *mdctx = EVP_MD_CTX_new();  // 创建EVP_MD_CTX结构，用于哈希运算
  if (!mdctx) {
    log_log("ERROR", "SERVER", "创建 EVP_MD_CTX 失败！");
    fprintf(stderr, "Unable to create EVP_MD_CTX\n");
    fclose(file);
    return;
  }

  const EVP_MD *digest = EVP_sha256();  // 获取SHA-256哈希算法的指针
  if (!digest) {
    log_log("ERROR", "SERVER", "无法获取SHA-256散列算法！");
    fprintf(stderr, "Unable to get SHA-256 digest\n");
    fclose(file);
    return;
  }

  unsigned char buffer[BUFFER_SIZE];  // 读取文件的缓冲区
  int bytes_read;
  unsigned char hash[EVP_MAX_MD_SIZE];  // 存储最终哈希值的数组
  unsigned int hash_len;                // 哈希值的长度

  if (EVP_DigestInit_ex(mdctx, digest, NULL) != 1) {
    log_log("ERROR", "SERVER", "初始化散列失败！");
    fprintf(stderr, "Digest init failed\n");
    EVP_MD_CTX_free(mdctx);
    fclose(file);
    return;
  }

  // 循环读取文件内容，并更新摘要
  while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, file)) > 0) {
    if (EVP_DigestUpdate(mdctx, buffer, bytes_read) != 1) {
      log_log("ERROR", "SERVER", "更新散列失败！");
      fprintf(stderr, "Digest update failed\n");
      EVP_MD_CTX_free(mdctx);
      fclose(file);
      return;
    }
  }

  // 最终计算摘要
  if (EVP_DigestFinal_ex(mdctx, hash, &hash_len) != 1) {
    log_log("ERROR", "SERVER", "计算散列失败！");
    EVP_MD_CTX_free(mdctx);
    fclose(file);
    return;
  }

  EVP_MD_CTX_free(mdctx);
  fclose(file);

  // 为哈希字符串分配内存
  *hash_out = malloc(hash_len * 2 + 1);  // 每个字节转为两个十六进制字符，加上空字符
  if (*hash_out == NULL) {
    fprintf(stderr, "为哈希字符串分配内存失败\n");
    return;
  }

  // 将哈希值转换为十六进制字符串
  char temp[3];  // 临时缓冲区，存储两个十六进制字符和空字符
  temp[2] = '\0';
  (*hash_out)[0] = '\0';  // 初始化字符串
  for (unsigned int i = 0; i < hash_len; i++) {
    snprintf(temp, sizeof(temp), "%02x", hash[i]);
    strcat(*hash_out, temp);  // 将转换后的十六进制字符串拼接到输出字符串
  }
}
